#pragma once

#ifndef LayoutNode_H
#define LayoutNode_H

#include "IntrusivePointer.h"
#include "Referenced.h"
#include "LayoutStructs.h"

namespace fusion
{
	namespace mode10
	{
		class Node;

		class LayoutNode : public Referenced
		{
		public:
			LayoutNode(Node* node, Ref<BaseLayoutParams> params);
			 virtual ~LayoutNode();

			Ref<BaseLayoutParams> GetLayoutParams() { return m_params; }
			unsigned int GetNodeID() { return m_NodeID; }
			int GetNodeName();

			void Measure(const Ref<MeasureSpec>& widthSpec, const Ref<MeasureSpec>& heightSpec);
			void Layout();
			void ReplaceParams(Ref<BaseLayoutParams>& params);
			virtual bool IsLayoutable() const { return false; }
			Ref<LayoutNode> GetParent();
			void SetParent(const Ref<LayoutNode>& parent);
			void RequestLayout();
			Node* GetNode() { return m_node; }
			int GetMeasuredWidth() const
			{
				return m_MeasuredWidth;
			}
			int GetMeasuredHeight() const
			{
				return m_MeasuredHeight;
			}
		protected:
			virtual void onMeasure(const Ref<MeasureSpec>& widthSpec, const Ref<MeasureSpec>& heightSpec);
			virtual void onLayout() {};
		private:
			int getSuggestedMinimumHeight();
			int getSuggestedMinimumWidth();

			static int getDefaultSize(int size, const Ref<MeasureSpec>& measureSpec);
			void setMeasuredDimension(int measuredWidth, int measuredHeight);
			// cannot keep Ref<Node>, otherwise node will become double reference with layout
		private:
			Node* m_node;
			Ref<BaseLayoutParams> m_params;
			Ref<LayoutNode> m_parent;
			unsigned int m_NodeID;
			int m_MeasuredWidth;
			int m_MeasuredHeight;
		protected:
			bool m_LayoutDirty;
		};
	}
}

#endif